package util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import core.Named;

/**
 * Name Sets are reduced sets
 * 
 * The name set is a collection which can contain only one instance of each
 * named object.  Objects can be removed and checked for based on their name
 * or by passing the named objects themselves.  The set is reduced in the
 * sense that it does not support the full collection interface.
 * 
 * In addition to implementing most of the Set interface a named set also
 * provides a means to access the contents of the set.
 * 
 * Note that add always overwrites the current contents of the set.
 * 
 * @version 1.1
 * @author Alexander Schearer <aas11@duke.edu>
 */
public class NameSet<E extends Named> implements Iterable<E> {

	private HashMap<String, E> myElements;

	public NameSet() {
		myElements = new HashMap<String, E>();
	}
	
	public E get(String o) {
		return myElements.get(o);
	}

	public boolean add(E o) {
		myElements.put(o.getName(), o);
		return true;
	}

	public boolean addAll(Iterable<E> c) {
		for (E n : c) {
			add(n);
		}
		return true;
	}
	
	public boolean addAll(E[] c) {
		for (int i = 0; i < c.length; i++)
		{
			add(c[i]);
		}
		return true;
	}

	public void clear() {
		myElements.clear();
	}

	public boolean contains(E o) {
		return myElements.containsKey(o.getName());
	}

	public boolean contains(String o) {
		return myElements.containsKey(o);
	}

	public boolean isEmpty() {
		return myElements.isEmpty();
	}
	/**
	 * This is a relatively expensive method
	 * @return
	 */
	public Iterator<E> iterator() {
		List<E> tmp = new ArrayList<E>();
		for (String n : myElements.keySet())
		{
			tmp.add(get(n));
		}
		return tmp.iterator();
	}

	public boolean remove(E o) {
		myElements.remove(o.getName());
		return true;
	}

	public boolean remove(String o) {
		myElements.remove(o);
		return true;
	}
	
	public boolean removeAll(Iterable<E> c) {
		for (E n : c) {
			remove(n);
		}
		return true;
	}

	public int size() {
		return myElements.size();
	}
}
